package com.naiterui.ehp.bs.im.network.protocl;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.annotation.Id;

import java.io.Serializable;
import java.util.Map;

/**
 * 用于IM通讯的数据消息实体
 * 该实体最终对应的是一个JSON结构
 * 本期通讯考虑使用JSON，后期切换成ProtoclBuffer
 * <P>File name : Message.java </P>
 * <P>Author : zhouyanxin </P>
 * <P>Date : 2015年6月18日 </P>
 */
public class Message<T> implements IChecker, Serializable {

    public static final int MESSAGE_VISUAL_TYPE_ALL = 0;
    public static final int MESSAGE_VISUAL_TYPE_DOCTOR = 1;
    public static final int MESSAGE_VISUAL_TYPE_PATIENT = 2;

    /**
     * 系统消息标识-用户
     */
    public static final int SYS_MSG_TYPE_CONSUMER = 0;
    /**
     * 系统消息标识-系统
     */
    public static final int SYS_MSG_TYPE_SYSTEM = 1;

    /**
     * 随机宣教KEY
     */
    public static final String EDUCACTION_KEY = "eduMessageKey";

    /**
     * 字段或域定义：<code>serialVersionUID</code>
     */
    private static final long serialVersionUID = 7259564633980137695L;

    /**
     * LOGGER
     */
    private static final Logger LOGGER = LoggerFactory.getLogger(Message.class);

    /**
     * 主键
     */
    @Id
    private String id;

    /**
     * 消息类型
     * 0：文本消息
     * 1：图片
     * 2：音频
     */
    private Integer type;

    /**
     * 发送者Id
     */
    private Chater from;

    /**
     * 接收者Id
     */
    private Chater to;

    /**
     * 就诊人ID
     */
    private Long inquirerId;

    /**
     * 0：患者2医生
     * 1：医生2患者
     */
    private Integer relation;

    /**
     * 消息内容
     * 1、一段文字
     * 2、一个URL（图片、音频）
     * 3、药方
     */
    private T content;

    /**
     * 发送时间
     * 单位：毫秒
     */
    private Long sendTime;

    /**
     * 消息会话信息
     */
    private Session session;

    /**
     * 上条消息发送平台：<code>lastPlatform</code>
     */
    private Integer lastPlatform;

    /**
     * 消息可见级别：<code>temp</code>
     */
    private Integer visualType;

    /**
     * 系统消息标识
     */
    private Integer sysMsgType;

    /**
     * 临时信息
     */
    private Map<String, String> temp;

    /**
     * 扩展字段
     */
    private Extend exd;

    /**
     * 构造函数(消息初始化可见等级为：全部可见,默认为用户消息)
     */
    public Message() {
        super();
        visualType = MESSAGE_VISUAL_TYPE_ALL;
        sysMsgType = SYS_MSG_TYPE_CONSUMER;
    }

    /**
     * 检测消息属性的完整性和正确性
     * Message.selfValidate()<BR>
     * <P>Author : zhouyanxin </P>
     * <P>Date : 2015年6月22日 </P>
     *
     * @return
     */
    @Override
    public boolean selfValidate() {

        // 消息基本属性检测
        boolean available = from.selfValidate() && to.selfValidate() && sendTime != null && sendTime > 0 && content != null;
        if (!available) {
            LOGGER.error("message attribute [sendTime] or [content] is invalid. {}, {}", sendTime, content);
        }

        // 消息类型如果不是文本消息，将根据各自定义的检测方法进行完整性和正确性的检测
        if (content instanceof String) {
            return available;
        } else {
            return available && ((IChecker) content).selfValidate();
        }
    }

    public Long getInquirerId() {
        return inquirerId;
    }

    public void setInquirerId(Long inquirerId) {
        this.inquirerId = inquirerId;
    }

    /**
     * @return int 取得域 type 的方法。
     */
    public int getType() {
        return type;
    }

    /**
     * @param type 对域 type 的设置方法.
     */
    public void setType(Integer type) {
        this.type = type;
    }

    /**
     * @return User 取得域 from 的方法。
     */
    public Chater getFrom() {
        return from;
    }

    /**
     * @param from 对域 from 的设置方法.
     */
    public void setFrom(Chater from) {
        this.from = from;
    }

    /**
     * @return User 取得域 to 的方法。
     */
    public Chater getTo() {
        return to;
    }

    /**
     * @param to 对域 to 的设置方法.
     */
    public void setTo(Chater to) {
        this.to = to;
    }

    /**
     * @return Integer 取得域 relation 的方法。
     */
    public Integer getRelation() {
        return relation;
    }

    /**
     * @param relation 对域 relation 的设置方法.
     */
    public void setRelation(Integer relation) {
        this.relation = relation;
    }

    /**
     * @return T 取得域 content 的方法。
     */
    public T getContent() {
        return content;
    }

    /**
     * @param content 对域 content 的设置方法.
     */
    public void setContent(T content) {
        this.content = content;
    }

    /**
     * @return Long 取得域 sendTime 的方法。
     */
    public Long getSendTime() {
        return sendTime;
    }

    /**
     * @param sendTime 对域 sendTime 的设置方法.
     */
    public void setSendTime(Long sendTime) {
        this.sendTime = sendTime;
    }

    /**
     * @return String 取得域 id 的方法。
     */
    public String getId() {
        return id;
    }

    /**
     * @param id 对域 id 的设置方法.
     */
    public void setId(String id) {
        this.id = id;
    }

    public Session getSession() {
        return session;
    }

    public void setSession(Session session) {
        this.session = session;
    }

    /**
     * @return Integer 取得域 lastPlatform 的方法。
     */
    public Integer getLastPlatform() {
        return lastPlatform;
    }

    /**
     * @param lastPlatform 对域 lastPlatform 的设置方法.
     */
    public void setLastPlatform(Integer lastPlatform) {
        this.lastPlatform = lastPlatform;
    }

    public Map<String, String> getTemp() {
        return temp;
    }

    public void setTemp(Map<String, String> temp) {
        this.temp = temp;
    }

    /**
     * @return Integer 取得域 visualType 的方法。
     */
    public Integer getVisualType() {
        return visualType;
    }

    /**
     * @param visualType 对域 visualType 的设置方法.
     */
    public void setVisualType(Integer visualType) {
        this.visualType = visualType;
    }

    public Extend getExd() {
        return exd;
    }

    public void setExd(Extend exd) {
        this.exd = exd;
    }

    public Integer getSysMsgType() {
        return sysMsgType;
    }

    public void setSysMsgType(Integer sysMsgType) {
        this.sysMsgType = sysMsgType;
    }

}
